﻿/***************************************************************************************
   Date    : February 7, 2007
   Purpose : Implement the ScoreSheetReader Class           
   Maintenance Log : 
   Revision		Date			Description 
   --------		---------		-----------------
	1.0		    7/02/2007		Initial Release

****************************************************************************************/

using System;
using System.Data;
using System.Data.OleDb;
using System.Threading;
using System.IO;

namespace Hclt.Msft.Til.CricketScoreboard
{
    public class ScoreSheetReader : IDisposable
    {
        #region Private Instance Variables

        private DataTable initialDataTable = new DataTable();

        #endregion

        #region IDisposable Members
        
        /// <summary>
        /// Disposes The InitialDataTable
        /// </summary>
        /// <param name="disposing">Argument Passes By Dispose()</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (initialDataTable != null) initialDataTable.Dispose();
            }
        }
        
        /// <summary>
        /// Disposes The InitialDataTable & Suppress The Garbage Collection. 
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        
        #endregion

        #region Public Constructor

        /// <summary>
        /// Public Constructor Of ScoreSheetReader Class
        /// Establishes The Connection With The Scoresheet.
        /// Fills The Data From The Scoresheet Into The InitialDataTable.
        /// </summary>
        public ScoreSheetReader()
        {
            
                string filePath = Utility.GetStringFromConfig("ScoreSheetPath", string.Empty);
                if (File.Exists(filePath))
                {
                    string tempFilePath = string.Concat(AppDomain.CurrentDomain.BaseDirectory, Utility.GetStringFromConfig("TempFileRelativePath",string.Empty));
                    File.Copy(filePath, tempFilePath, true);

                    String sConnectionString = string.Concat(Utility.GetStringFromConfig("ExcelProviderString", string.Empty), tempFilePath, " ;");
                    String queryString = Utility.GetStringFromConfig("QueryString", string.Empty);
                    
                    OleDbDataAdapter initialAdapter = new OleDbDataAdapter(queryString, sConnectionString);
                    DataSet initialDataset = new DataSet();
                    initialAdapter.Fill(initialDataset);

                    if (initialDataset != null && initialDataset.Tables.Count > 0)
                    {
                        initialDataTable = initialDataset.Tables[0];
                        initialDataTable.Locale = Thread.CurrentThread.CurrentCulture;
                    }
                    initialAdapter.Dispose();
                    int inningsColumn = Utility.GetIntFromConfig("ColumnInnings", 4);
                    int inningsRow = Utility.GetIntFromConfig("RowInnings", 0);                    
                    string inningsCheck = Convert.ToString(initialDataTable.Rows[inningsRow][inningsColumn]).Equals(DBNull.Value) ? "First Inning" : Convert.ToString(initialDataTable.Rows[inningsRow][inningsColumn]);

                    if (inningsCheck == Convert.ToString(Innings.First))
                    {
                        queryString = queryString.Replace("Team details", Utility.GetStringFromConfig("FirstInningsScoresheet", "First Inning"));
                    }
                    else
                    {
                        queryString = queryString.Replace("Team details", Utility.GetStringFromConfig("SecondInningsScoresheet", "Second Inning"));
                    }

                    initialAdapter = new OleDbDataAdapter(queryString, sConnectionString);
                    initialDataset = new DataSet();
                    initialAdapter.Fill(initialDataset);

                    if (initialDataset != null && initialDataset.Tables.Count > 0)
                    {
                        initialDataTable = initialDataset.Tables[0];
                        initialDataTable.Locale = Thread.CurrentThread.CurrentCulture;
                    }
                    initialAdapter.Dispose();
                }
                else
                {
                    System.Diagnostics.Trace.WriteLine(string.Concat(DateTime.Now, " :: ", filePath, " File not found.", Environment.NewLine)); 
                }

        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Creates A BatsmanInfoCollection Object After Reading Information From InitialDataTable.
        /// Total Elements Inserted Into BatsmanInfoCollection Equals To The Total Number Of Players.
        /// </summary>
        /// <returns>BatsmanInfoCollection Object Containing Information Of Batting Team Members</returns> 
        private BatsmanInfoCollection GetBatsmanCollection()
        {
            int noOfRows = Utility.GetIntFromConfig("NoOfPlayers", 7);

            int batsmanNameColumn = Utility.GetIntFromConfig("ColumnPlayerName", 1);

            int batsmanScoreColumn = Utility.GetIntFromConfig("ColumnBatsmanTotalScore", 32);
            int batsmanTotalBallsColumn = Utility.GetIntFromConfig("ColumnBatsmanTotalBalls", 33);
            int batsmanTotalFoursColumn = Utility.GetIntFromConfig("ColumnBatsmanTotalFours", 34);
            int batsmanTotalSixesColumn = Utility.GetIntFromConfig("ColumnBatsmanTotalSixes", 35);
            int batsmanStrikeRateColumn = Utility.GetIntFromConfig("ColumnBatsmanStrikerate", 36);
            int batsmanStatusColumn = Utility.GetIntFromConfig("ColumnBatsmanStatus", 37);

            BatsmanInfo batsmanInfoObj = null;
            BatsmanInfoCollection batsmanInfoCollectionObj = new BatsmanInfoCollection();
            DataRowCollection batsmanInfoRow = initialDataTable.Rows;

            for (int counter = 0; counter < noOfRows; counter++)
            {
                if (batsmanInfoRow[counter][batsmanNameColumn] == DBNull.Value || string.IsNullOrEmpty(Convert.ToString(batsmanInfoRow[counter][batsmanNameColumn])))
                {
                    continue;
                }
                else
                {
                    batsmanInfoObj = new BatsmanInfo();

                    batsmanInfoObj.BatsmanName = Convert.ToString(batsmanInfoRow[counter][batsmanNameColumn]);

                    batsmanInfoObj.BatsmanScore = ReadIntFromCell(counter, batsmanScoreColumn);
                    
                    string status = batsmanInfoRow[counter][batsmanStatusColumn] == DBNull.Value ? string.Empty : Convert.ToString(batsmanInfoRow[counter][batsmanStatusColumn]);
                    status = status.Trim();
                    if(string.IsNullOrEmpty(status))
                    {
                        batsmanInfoObj.Status = BatsmanStatus.Dnb;
                    }
                    else if(status.Equals("Playing",StringComparison.CurrentCultureIgnoreCase))
                    {
                        batsmanInfoObj.Status = BatsmanStatus.Playing;
                        batsmanInfoObj.StatusDescription = "Not Out";
                    }
                    else if(status.Equals("Retired",StringComparison.CurrentCultureIgnoreCase))
                    {
                        batsmanInfoObj.Status = BatsmanStatus.Retired;
                        batsmanInfoObj.StatusDescription = "Retired";
                    }
                    else
                    {
                        batsmanInfoObj.Status = BatsmanStatus.Out;
                        batsmanInfoObj.StatusDescription = status;
                    }                    
                    
                    float strikeRate;
                    float.TryParse(batsmanInfoRow[counter][batsmanStrikeRateColumn] == DBNull.Value ? "0" : Convert.ToString(batsmanInfoRow[counter][batsmanStrikeRateColumn]), out strikeRate);
                    batsmanInfoObj.StrikeRate = strikeRate;

                    batsmanInfoObj.TotalBallsPlayed = ReadIntFromCell(counter, batsmanTotalBallsColumn);

                    batsmanInfoObj.TotalFours = ReadIntFromCell(counter, batsmanTotalFoursColumn);

                    batsmanInfoObj.TotalSixes = ReadIntFromCell(counter, batsmanTotalSixesColumn);


                    batsmanInfoCollectionObj.Add(batsmanInfoObj);
                }
            }

            return batsmanInfoCollectionObj;
        }

        /// <summary>
        /// Creates A BowlerInfoCollection Object After Reading Information From InitialDataTable.
        /// Total Elements Inserted Into BowlerInfoCollection Equals To The Total Number Of Players.
        /// </summary>
        /// <returns>BowlerInfoCollection Object Containing Information Of Fielding Team Members</returns>
        private BowlerInfoCollection GetBowlerCollection()
        {

            int noOfRows = Utility.GetIntFromConfig("NoOfPlayers", 7);

            int bowlerNameColumn = Utility.GetIntFromConfig("ColumnPlayerName", 1);
            int totalBallsColumn = Utility.GetIntFromConfig("ColumnBowlerTotalBalls", 33);
            int totalRunsColumn = Utility.GetIntFromConfig("ColumnBowlerGivenRuns", 32);
            int totalWicketsColumn = Utility.GetIntFromConfig("ColumnBowlerTotalWickets", 34);
            int bowlerCounterStart = Utility.GetIntFromConfig("ColumnBowlerCounter", 22);
            BowlerInfo bowlerInfoObj = null;


            BowlerInfoCollection bowlerInfoCollectionObj = new BowlerInfoCollection();
            DataRowCollection bowlerInfoRow = initialDataTable.Rows;

            for (int counter = bowlerCounterStart; counter < noOfRows + bowlerCounterStart; counter++)
            {
                if (bowlerInfoRow[counter][bowlerNameColumn] == DBNull.Value || string.IsNullOrEmpty(Convert.ToString(bowlerInfoRow[counter][bowlerNameColumn])))
                {
                    continue;
                }
                else
                {
                    bowlerInfoObj = new BowlerInfo();

                    bowlerInfoObj.BowlerName = Convert.ToString(bowlerInfoRow[counter][bowlerNameColumn]);

                    bowlerInfoObj.TotalBalls = ReadIntFromCell(counter, totalBallsColumn);
                    bowlerInfoObj.TotalRuns = ReadIntFromCell(counter, totalRunsColumn);
                    bowlerInfoObj.TotalWickets = ReadIntFromCell(counter, totalWicketsColumn);

                    if (bowlerInfoRow[counter][totalBallsColumn] == DBNull.Value)
                    {
                        bowlerInfoObj.Status = BowlerStatus.Rest;
                    }
                    else
                    {
                        bowlerInfoObj.Status = Convert.ToInt32(bowlerInfoRow[counter][totalBallsColumn]) % 6 == 0 ? BowlerStatus.Rest : BowlerStatus.Bowling;
                    }


                    bowlerInfoCollectionObj.Add(bowlerInfoObj);
                }
            }

            return bowlerInfoCollectionObj;            
        }

        /// <summary>
        /// Creates A ExtrasInfo Object After Reading Information From InitialDataTable.
        /// Holds The Information About The Different Extras Give Byt The Fielding Team.
        /// </summary>
        /// <returns>ExtrasInfo Object Containing Information Of Extras</returns>
        private ExtrasInfo GetExtrasInfo()
        {
            int noBallRow = Utility.GetIntFromConfig("RowNoBall", 12);
            int noBallColumn = Utility.GetIntFromConfig("ColumnNoBall", 32);
            int wideBallRow = Utility.GetIntFromConfig("RowWideBall", 13);
            int wideBallColumn = Utility.GetIntFromConfig("ColumnWideBall", 32);
            int byeRow = Utility.GetIntFromConfig("RowBye", 14);
            int byeColumn = Utility.GetIntFromConfig("ColumnBye", 32);
            ExtrasInfo extraInfoObj = new ExtrasInfo();
            DataRowCollection extrasInfoRow = initialDataTable.Rows;
    
            extraInfoObj.TotalNoBalls = ReadIntFromCell(noBallRow,noBallColumn);
            extraInfoObj.TotalWideBalls = ReadIntFromCell(wideBallRow,wideBallColumn);
            extraInfoObj.TotalByes = ReadIntFromCell(byeRow, byeColumn);

            return extraInfoObj;
        }

        /// <summary>
        /// Function To Get The Total Score Of Batting Team From The InitialDataTable.
        /// </summary>
        /// <returns>Integer With Value Equals To Total Score Of The Batting Team</returns>
        private int GetTeamTotalScore()
        {
            int rowNum = Utility.GetIntFromConfig("RowTotalScore", 16);
            int colNum = Utility.GetIntFromConfig("ColumnTotalScore", 32);

            int teamTotalScore = ReadIntFromCell(rowNum, colNum);

            return teamTotalScore;
        }

        /// <summary>
        /// Function To Get The Total Balls Played By The Batting Team From The InitialDataTable.
        /// </summary>
        /// <returns>Integer With Value Equals To Total Balls Played By The Batting Team</returns>
        private int GetTotalBallsPlayed()
        {
            int rowNum = Utility.GetIntFromConfig("RowTotalBalls", 33);
            int colNum = Utility.GetIntFromConfig("ColumnTotalBalls", 32);

            int totalBallsPlayed = ReadIntFromCell(rowNum, colNum);
            
            return totalBallsPlayed;
        }

        /// <summary>
        /// Function To Get The Custom Message Inserted Into The Scoresheet From The InitialDataTable.
        /// </summary>
        /// <param name="scoreBoardObj">Scoreboard Object To Check Wheter Message Is To Be Displayed.</param>
        private void GetMatchSummaryReport(Scoreboard scoreBoardObj)
        {
            int rowNum = Utility.GetIntFromConfig("RowMatchSummaryReport", 28);
            int colNum = Utility.GetIntFromConfig("ColumnMatchSummaryReport", 37);

            string matchSummaryReport = ReadStringFromCell(rowNum, colNum);
            matchSummaryReport = matchSummaryReport.Trim();
            
            if(string.IsNullOrEmpty(matchSummaryReport))
            {
                scoreBoardObj.InningsOver = false;
            }
            else
            {
                scoreBoardObj.InningsOver = true;
            }
            
            scoreBoardObj.MatchSummary = matchSummaryReport;
        }

        /// <summary>
        /// Function To Get The Batting Team Name From The InitialDataTable.
        /// </summary>
        /// <returns>String With The Value Equal To Batting Team Name.</returns>
        private string GetBattingTeamName()
        {
            int rowNum = Utility.GetIntFromConfig("RowBattingTeamName", 22);
            int colNum = Utility.GetIntFromConfig("ColumnBattingTeamName", 37);

            string battingTeamName = ReadStringFromCell(rowNum, colNum);
            
            return battingTeamName;
        }

        /// <summary>
        /// Function To Get The Fielding Team Name From The InitialDataTable.
        /// </summary>
        /// <returns>String With The Value Equal To Fielding Team Name.</returns>
        private string GetFieldingTeamName()
        {
            int rowNum = Utility.GetIntFromConfig("RowFieldingTeamName", 25);
            int colNum = Utility.GetIntFromConfig("ColumnFieldingTeamName", 37);

            string fieldingTeamName = ReadStringFromCell(rowNum, colNum);
            
            return fieldingTeamName;
        }       
        
        /// <summary>
        /// Function To Read A String From A Particular Cell From InitialDataTable.
        /// </summary>
        /// <param name="rowNum">Row Number Of The Required Cell.</param>
        /// <param name="colNum">Column Number Of The Required Cell.</param>
        /// <returns>String With The Value Equal To The Required Cell.</returns>
        private string ReadStringFromCell(int rowNum, int colNum)
        {
            return initialDataTable.Rows[rowNum][colNum] == DBNull.Value ? string.Empty : Convert.ToString(initialDataTable.Rows[rowNum][colNum]);
        }

        /// <summary>
        /// Function To Read An Integer From A Particular Cell From InitialDataTable.
        /// </summary>
        /// <param name="rowNum">Row Number Of The Required Cell.</param>
        /// <param name="colNum">Column Number Of The Required Cell.</param>
        /// <returns>Integer With The Value Equal To The Required Cell.</returns>
        private int ReadIntFromCell(int rowNum, int colNum)
        {
            int returnValue = 0;
            if (initialDataTable.Rows[rowNum][colNum] != DBNull.Value)
            {
                string cellValue = Convert.ToString(initialDataTable.Rows[rowNum][colNum]);
                Int32.TryParse(cellValue, out returnValue);
            }
            return returnValue;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Function To Create A Scoreboard Object Holding All The Relevant Data.
        /// </summary>
        /// <returns>Scoreboard Object Holding All The Relevant Data.</returns>
        public Scoreboard GetScoreBoard()
        {
            Scoreboard scoreBoardObj = new Scoreboard();
            scoreBoardObj.BatsmanDetails = GetBatsmanCollection();
            scoreBoardObj.BowlerDetails = GetBowlerCollection();
            scoreBoardObj.ExtrasDetails = GetExtrasInfo();
            scoreBoardObj.TeamTotalScore = GetTeamTotalScore();
            scoreBoardObj.TeamTotalBalls = GetTotalBallsPlayed();
            scoreBoardObj.BattingTeamName = GetBattingTeamName();
            scoreBoardObj.FieldingTeamName = GetFieldingTeamName();
            GetMatchSummaryReport(scoreBoardObj);

            return scoreBoardObj;
        }

        #endregion
    }
}
